import queue


def Nextstep2(lukou, group1, group2, data1, data2, data3):
    """
    二相位路口
    :param lukou: the obj of a tow phase crossing
    :param group1: the signalgroup1
    :param group2: the signalgroup2
    :param data1: the datacollection1
    :param data2: the datacollection2
    :param data3: the datacollection3
    :return: none
    """

    '''new_2'''
    lukou.queue1.put(data1.GetResult("NVEHICLES", "SUM", 0))
    lukou.queue1.get()
    lukou.queue2.put(data2.GetResult("NVEHICLES", "SUM", 0))
    lukou.queue2.get()
    lukou.queue3.put(data1.GetResult("NVEHICLES", "SUM", 0))
    lukou.queue3.get()
    lukou.queue4.put(data2.GetResult("NVEHICLES", "SUM", 0))
    lukou.queue4.get()
    '''end new'''

    if lukou.mainflag:  # 开启信号控制
        # 绿灯
        if lukou.brt_time < lukou.t_green:
            lukou.brt_time += 1

        elif lukou.green_long_flag:
            # 执行绿灯延长
            lukou.brt_time = lukou.brt_time - lukou.delta_t + 1
            lukou.other_time = lukou.other_time + lukou.delta_t
            lukou.green_long_flag = False
            mess = "路口" + str(lukou.lukou_ID) + "绿灯延长" + str(lukou.delta_t) + "秒"
            # QMessageBox.information(self, '提示', mess, QMessageBox.Yes | QMessageBox.No)
            print(mess)

        else:
            # 变灯
            lukou.brt_time = 1
            lukou.mainflag = False
            group2.SetAttValue("TYPE", 2)  # other变绿
            group1.SetAttValue("TYPE", 3)  # brt变红

    else:
        # 红灯
        # '''new_2'''
        if lukou.red_short_flag and lukou.other_time == lukou.t_red - lukou.delta_t_g_max:
            for j in range(40):  # 求四个q
                temp = int(lukou.queue3.get())
                lukou.q1 += temp
                lukou.queue1.put(temp)
                temp = int(lukou.queue4.get())
                lukou.q2 += temp
                lukou.queue2.put(temp)
            lukou.q1 = lukou.q1 / 40
            lukou.q2 = lukou.q2 / 40

            # 计算PI
            PI = 0.5 * lukou.q1 * lukou.t_red * lukou.t_red + lukou.M * lukou.delta_t + 0.5 * lukou.q2 * lukou.t_green * lukou.t_green

            # 计算delta_PI
            for j in range(40):  # 求第一相位的Q1和Q2
                temp = int(lukou.queue1.get())
                if 40 - lukou.t_red < j <= 40 - lukou.delta_t:
                    lukou.duilie1 += temp
                elif j > 40 - lukou.delta_t:
                    lukou.duilie2 += temp
                lukou.queue1.put(temp)

            for j in range(40):  # 求第二相位的Q3
                temp = int(lukou.queue2.get())
                if j > 40 - lukou.delta_t:
                    lukou.duilie3 += temp
                lukou.queue2.put(temp)

            delta_PI = lukou.duilie3 * (lukou.t_green + lukou.delta_t / 2) - (
                    lukou.M + lukou.duilie1 + lukou.duilie2 / 2) * lukou.delta_t
            lukou.duilie1, lukou.duilie2, lukou.duilie3 = 0, 0, 0
            # 结束

            if delta_PI <= 0:
                lukou.brt_time = lukou.brt_time - lukou.delta_t
                lukou.other_time = lukou.other_time + lukou.delta_t + 1
                lukou.red_short_flag = False
                mess = "路口" + str(lukou.lukou_ID) + "红灯缩短" + str(lukou.delta_t) + "秒" + "delta_PI:" + str(delta_PI)
                print(mess)

        elif lukou.other_time < 30:
            lukou.other_time = lukou.other_time + 1

        else:
            # 变灯
            lukou.other_time = 1
            lukou.mainflag = True
            group2.SetAttValue("TYPE", 3)  # other变红
            group1.SetAttValue("TYPE", 2)  # brt变绿


def Getbus2(Vissim, lukou1, detector1, detector2):
    # 两相位路口检测到公交车
    if detector2.AttValue("IMPULSE") == 1:
        # 速度调节
        if lukou1.brt_time + lukou1.l2 * 3.6 / lukou1.v_bus > lukou1.t_green + lukou1.delta_t_g_max and lukou1.brt_time + lukou1.l2 * 3.6 / lukou1.v_bus < lukou1.t_green + lukou1.t_red - lukou1.delta_t_r_max:
            bus_id = int(detector2.SetAttValue("VEHICLEID"))  # 获取公交车的ID
            bus = Vissim.Net.Vehicles.GetVehicleByNumber(bus_id)
            bus_speed = (lukou1.l2 - lukou1.l1) / (lukou1.t_green - lukou1.brt_time) * 3.6
            # QMessageBox.information(self, '提示', '速度调节', QMessageBox.Yes | QMessageBox.No)
            print('速度调节')
            bus.SetAttValue("SPEED", bus_speed)
            bus.SetAttValue("DESIREDSPEED", bus_speed)
            lukou1.delta_t = lukou1.delta_t_g_max
            lukou1.green_long_flag = True
            lukou1.speed_flag = True

    if detector1.AttValue("IMPULSE") == 1:
        # 信号调节
        import math
        if not lukou1.speed_flag:
            # 且未执行加速

            if lukou1.brt_time + lukou1.l1 * 3.6 / lukou1.v_bus > lukou1.t_green:
                # 绿灯延长
                lukou1.delta_t = lukou1.brt_time + int(math.ceil(lukou1.l1 * 3.6 / lukou1.v_bus)) - lukou1.t_green

                '''new_2'''
                temp = 0
                for j in range(40):  # 求四个q
                    temp = int(lukou1.queue3.get())
                    lukou1.q1 += temp
                    lukou1.queue1.put(temp)
                    temp = int(lukou1.queue4.get())
                    lukou1.q2 += temp
                    lukou1.queue2.put(temp)
                lukou1.q1 = lukou1.q1 / 40
                lukou1.q2 = lukou1.q2 / 40

                # 计算PI
                PI = 0.5 * lukou1.q1 * lukou1.t_red * lukou1.t_red + lukou1.M * (
                            lukou1.t_red - lukou1.delta_t) + 0.5 * lukou1.q2 * lukou1.t_green * lukou1.t_green

                # 计算delta_PI
                for j in range(40):  # 求第二相位的Q1和Q2
                    temp = int(lukou1.queue2.get())
                    if 40 - lukou1.t_red - lukou1.delta_t < j <= 40 - lukou1.delta_t:
                        lukou1.duilie1 += temp
                    elif j > 40 - lukou1.delta_t:
                        lukou1.duilie2 += temp
                    lukou1.queue2.put(temp)

                for j in range(40):  # 求第一相位的Q3
                    temp = int(lukou1.queue1.get())
                    if j > 40 - lukou1.delta_t:
                        lukou1.duilie3 += temp
                    lukou1.queue1.put(temp)

                delta_PI = (lukou1.duilie1 + lukou1.duilie2 / 2) * lukou1.delta_t - lukou1.M * (
                        lukou1.t_red - lukou1.delta_t) - lukou1.duilie3 * (lukou1.t_red - lukou1.delta_t / 2)
                lukou1.duilie1 = 0
                lukou1.duilie2 = 0
                lukou1.duilie3 = 0

                if delta_PI <= 0:
                    lukou1.green_long_flag = True
                else:
                    print('不能执行绿灯延长')
                '''end new_2'''

            if lukou1.t_red - lukou1.delta_t_r_max <= lukou1.other_time + lukou1.l1 * 3.6 / lukou1.v_bus < lukou1.t_red:
                # 红灯缩短
                lukou1.delta_t = lukou1.t_red - int(math.ceil(lukou1.other_time + lukou1.l1 * 3.6 / lukou1.v_bus)) + 1
                lukou1.red_short_flag = True

        else:
            # 如果执行过加速，将速度降低到正常速度，因为要到路口了
            bus_id = int(detector1.AttValue("VEHICLEID"))
            bus = Vissim.Net.Vehicles.GetVehicleByNumber(bus_id)
            bus.SetAttValue("SPEED", 35.0)
            bus.SetAttValue("DESIREDSPEED", 35.0)
            lukou1.speed_flag = False

            '''new_2'''
            temp = 0

            for j in range(40):  # 求四个q
                temp = int(lukou1.queue3.get())
                lukou1.q1 += temp
                lukou1.queue1.put(temp)
                temp = int(lukou1.queue4.get())
                lukou1.q2 += temp
                lukou1.queue2.put(temp)
            lukou1.q1 = lukou1.q1 / 40
            lukou1.q2 = lukou1.q2 / 40

            # 计算PI
            PI = 0.5 * lukou1.q1 * lukou1.t_red * lukou1.t_red + lukou1.M * lukou1.delta_t + 0.5 * lukou1.q2 * lukou1.t_green * lukou1.t_green

            # 计算delta_PIP
            # 求第二相位的Q1和Q2
            for j in range(40):
                temp = int(lukou1.queue2.get())
                if (40 - lukou1.t_red - lukou1.delta_t) < j <= (40 - lukou1.delta_t):
                    lukou1.duilie1 += temp
                elif j > (40 - lukou1.delta_t):
                    lukou1.duilie2 += temp
                lukou1.queue2.put(temp)

            # 求第一相位的Q3
            for j in range(40):
                temp = int(lukou1.queue1.get())
                if j > (40 - lukou1.delta_t):
                    lukou1.duilie3 += temp
            lukou1.queue1.put(temp)
            delta_PI = (lukou1.duilie1 + lukou1.duilie2 / 2) * lukou1.delta_t - lukou1.M * (
                    lukou1.t_red - lukou1.delta_t) - lukou1.duilie3 * (lukou1.t_red - lukou1.delta_t / 2)
            lukou1.duilie1 = 0
            lukou1.duilie2 = 0
            lukou1.duilie3 = 0

            if delta_PI <= 0:
                lukou1.green_long_flag = True
            '''end new_2'''


def Nextstep4(lukou, group1, group2, group3, group4, data1, data2, data3, data4):
    lukou.queue1.put(data1.GetResult("NVEHICLES", "SUM", 0))
    lukou.queue1.get()
    lukou.queue2.put(data2.GetResult("NVEHICLES", "SUM", 0))
    lukou.queue2.get()
    lukou.queue3.put(data3.GetResult("NVEHICLES", "SUM", 0))
    lukou.queue3.get()
    lukou.queue4.put(data4.GetResult("NVEHICLES", "SUM", 0))
    lukou.queue4.get()

    def case1():
        if lukou.time_1 < lukou.t_g_1:
            # 正常读秒
            lukou.time_1 += 1

        elif lukou.green_long_flag:
            # 绿灯延长
            temp = 0
            for j in range(60):
                # 求四个q
                temp = int(lukou.queue1.get())
                lukou.q1 += temp
                lukou.queue1.put(temp)
                temp = int(lukou.queue2.get())
                lukou.q2 += temp
                lukou.queue2.put(temp)
                temp = int(lukou.queue3.get())
                lukou.q3 += temp
                lukou.queue3.put(temp)
                temp = int(lukou.queue4.get())
                lukou.q4 += temp
                lukou.queue4.put(temp)
            lukou.q1 = lukou.q1 / 60
            lukou.q2 = lukou.q2 / 60
            lukou.q3 = lukou.q3 / 60
            lukou.q4 = lukou.q4 / 60

            # 计算PI
            PI = 0.5 * (lukou.q1 + lukou.q2) * lukou.r1 * (lukou.T - lukou.t_g_1) * (
                        lukou.T - lukou.t_g_1) + lukou.M * (lukou.T - lukou.t_g_1 - lukou.delta_t) + 0.5 * (
                             lukou.q1 + lukou.q2) * lukou.r2 * (lukou.T - lukou.t_g_2) * (
                             lukou.T - lukou.t_g_2) + 0.5 * (lukou.q3 + lukou.q4) * lukou.r3 * (
                             lukou.T - lukou.t_g_3) * (lukou.T - lukou.t_g_3) + 0.5 * (
                             lukou.q3 + lukou.q4) * lukou.r4 * (lukou.T - lukou.t_g_4) * (lukou.T - lukou.t_g_4)

            # 计算delta_PI
            delta_PI = 0.5 * (lukou.q1 + lukou.q2) * lukou.r1 * (
                        (lukou.T - lukou.t_g_1 - lukou.delta_t) * (lukou.T - lukou.t_g_1 - lukou.delta_t) - (
                            lukou.T - lukou.t_g_1) * (lukou.T - lukou.t_g_1)) - lukou.M * (
                                   lukou.T - lukou.t_g_1 - lukou.delta_t) + 0.5 * (lukou.q1 + lukou.q2) * lukou.r2 * ((
                                                                                                                                  lukou.T - lukou.t_g_2 + (
                                                                                                                              int)(
                                                                                                                              lukou.delta_t * (
                                                                                                                                          lukou.t_g_2 / (
                                                                                                                                              lukou.t_g_2 + lukou.t_g_3 + lukou.t_g_4)))) * (
                                                                                                                                  lukou.T - lukou.t_g_2 + (
                                                                                                                              int)(
                                                                                                                              lukou.delta_t * (
                                                                                                                                          lukou.t_g_2 / (
                                                                                                                                              lukou.t_g_2 + lukou.t_g_3 + lukou.t_g_4)))) - (
                                                                                                                                  lukou.T - lukou.t_g_2) * (
                                                                                                                                  lukou.T - lukou.t_g_2)) + 0.5 * (
                                   lukou.q3 + lukou.q4) * lukou.r3 * ((lukou.T - lukou.t_g_3 + int(
                lukou.delta_t * (lukou.t_g_3 / (lukou.t_g_2 + lukou.t_g_3 + lukou.t_g_4)))) * (
                                                                                  lukou.T - lukou.t_g_3 + int(
                                                                              lukou.delta_t * (lukou.t_g_3 / (
                                                                                          lukou.t_g_2 + lukou.t_g_3 + lukou.t_g_4)))) - (
                                                                                  lukou.T - lukou.t_g_3) * (
                                                                                  lukou.T - lukou.t_g_3)) + 0.5 * (
                                   lukou.q3 + lukou.q4) * lukou.r4 * ((lukou.T - lukou.t_g_4 + int(
                lukou.delta_t * (lukou.t_g_4 / (lukou.t_g_2 + lukou.t_g_3 + lukou.t_g_4)))) * (
                                                                                  lukou.T - lukou.t_g_4 + int(
                                                                              lukou.delta_t * (lukou.t_g_4 / (
                                                                                          lukou.t_g_2 + lukou.t_g_3 + lukou.t_g_4)))) - (
                                                                                  lukou.T - lukou.t_g_4) * (
                                                                                  lukou.T - lukou.t_g_4))
            lukou.q1, lukou.q2, lukou.q3, lukou.q4 = 0, 0, 0, 0

            if delta_PI <= 0:
                lukou.time_1 = lukou.time_1 + 1 - lukou.delta_t
                lukou.time_2 = lukou.time_2 + int(lukou.delta_t / 4)
                lukou.time_3 = lukou.time_3 + (lukou.delta_t - 2 * int(lukou.delta_t / 4))
                lukou.time_4 = lukou.time_4 + int(lukou.delta_t / 4)
                lukou.green_long_flag = False
                mess = "路口" + str(lukou.lukou_ID) + "绿灯延长" + str(lukou.delta_t) + "秒" + "delta_PI:" + str(delta_PI)
                # QMessageBox.information(self, '提示', mess, QMessageBox.Yes | QMessageBox.No)
                print(mess)

        else:
            # 变灯
            lukou.time_1 = 1
            lukou.main_flag = 2
            group1.SetAttValue("TYPE", 3)  # 1变红
            group2.SetAttValue("TYPE", 2)  # 2变绿
            if lukou.red_short_flag:
                # 红灯缩短
                for j in range(60):
                    # 求四个q
                    temp = int(lukou.queue1.get())
                    lukou.q1 += temp
                    lukou.queue1.put(temp)
                    temp = int(lukou.queue2.get())
                    lukou.q2 += temp
                    lukou.queue2.put(temp)
                    temp = int(lukou.queue3.get())
                    lukou.q3 += temp
                    lukou.queue3.put(temp)
                    temp = int(lukou.queue4.get())
                    lukou.q4 += temp
                    lukou.queue4.put(temp)
                lukou.q1 = lukou.q1 / 60
                lukou.q2 = lukou.q2 / 60
                lukou.q3 = lukou.q3 / 60
                lukou.q4 = lukou.q4 / 60

                # 计算PI
                PI = 0.5 * (lukou.q1 + lukou.q2) * lukou.r1 * (lukou.T - lukou.t_g_1) * (
                            lukou.T - lukou.t_g_1) + lukou.M * lukou.delta_t + 0.5 * (
                                 lukou.q1 + lukou.q2) * lukou.r2 * (lukou.T - lukou.t_g_2) * (
                                 lukou.T - lukou.t_g_2) + 0.5 * (lukou.q3 + lukou.q4) * lukou.r3 * (
                                 lukou.T - lukou.t_g_3) * (lukou.T - lukou.t_g_3) + 0.5 * (
                                 lukou.q3 + lukou.q4) * lukou.r4 * (lukou.T - lukou.t_g_4) * (lukou.T - lukou.t_g_4)

                # 计算delta_PI
                delta_PI = 0.5 * (lukou.q1 + lukou.q2) * lukou.r1 * (
                            (lukou.T - lukou.t_g_1 - lukou.delta_t) * (lukou.T - lukou.t_g_1 - lukou.delta_t) - (
                                lukou.T - lukou.t_g_1) * (lukou.T - lukou.t_g_1)) - lukou.M * lukou.delta_t + 0.5 * (
                                       lukou.q1 + lukou.q2) * lukou.r2 * ((lukou.T - lukou.t_g_2 + int(
                    lukou.delta_t * (lukou.t_g_2 / (lukou.t_g_2 + lukou.t_g_3 + lukou.t_g_4)))) * (
                                                                                      lukou.T - lukou.t_g_2 + int(
                                                                                  lukou.delta_t * (lukou.t_g_2 / (
                                                                                              lukou.t_g_2 + lukou.t_g_3 + lukou.t_g_4)))) - (
                                                                                      lukou.T - lukou.t_g_2) * (
                                                                                      lukou.T - lukou.t_g_2)) + 0.5 * (
                                       lukou.q3 + lukou.q4) * lukou.r3 * ((lukou.T - lukou.t_g_3 + int(
                    lukou.delta_t * (lukou.t_g_3 / (lukou.t_g_2 + lukou.t_g_3 + lukou.t_g_4)))) * (
                                                                                      lukou.T - lukou.t_g_3 + int(
                                                                                  lukou.delta_t * (lukou.t_g_3 / (
                                                                                              lukou.t_g_2 + lukou.t_g_3 + lukou.t_g_4)))) - (
                                                                                      lukou.T - lukou.t_g_3) * (
                                                                                      lukou.T - lukou.t_g_3)) + 0.5 * (
                                       lukou.q3 + lukou.q4) * lukou.r4 * ((lukou.T - lukou.t_g_4 + int(
                    lukou.delta_t * (lukou.t_g_4 / (lukou.t_g_2 + lukou.t_g_3 + lukou.t_g_4)))) * (
                                                                                      lukou.T - lukou.t_g_4 + int(
                                                                                  lukou.delta_t * (lukou.t_g_4 / (
                                                                                              lukou.t_g_2 + lukou.t_g_3 + lukou.t_g_4)))) - (
                                                                                      lukou.T - lukou.t_g_4) * (
                                                                                      lukou.T - lukou.t_g_4))
                lukou.q1 = 0
                lukou.q2 = 0
                lukou.q3 = 0
                lukou.q4 = 0

                if delta_PI <= 0:
                    lukou.time_1 = lukou.time_1 - lukou.delta_t
                    lukou.time_2 = lukou.time_2 + int(lukou.delta_t / 4)
                    lukou.time_3 = lukou.time_3 + (lukou.delta_t - 2 * int(lukou.delta_t / 4))
                    lukou.time_4 = lukou.time_4 + int(lukou.delta_t / 4)
                    lukou.red_short_flag = False
                    mess = "路口" + str(lukou.lukou_ID) + "红灯缩短" + str(lukou.delta_t) + "秒" + "delta_PI:" + str(delta_PI)
                    # QMessageBox.information(self, '提示', mess, QMessageBox.Yes | QMessageBox.No)
                    print(mess)

    def case2():
        if lukou.time_2 < lukou.t_g_2:
            lukou.time_2 += 1
        else:
            # 变灯
            lukou.time_2 = 1
            lukou.main_flag = 3
            group2.SetAttValue("TYPE", 3)  # 2变红
            group3.SetAttValue("TYPE", 2)  # 3变绿

    def case3():
        if lukou.time_3 < lukou.t_g_3:
            lukou.time_3 += 1
        else:
            # 变灯
            lukou.time_3 = 1
            lukou.main_flag = 4
            group3.SetAttValue("TYPE", 3)  # 3变红
            group4.SetAttValue("TYPE", 2)  # 4变绿

    def case4():
        if lukou.time_4 < lukou.t_g_4:
            lukou.time_4 += 1
        else:
            # 变灯
            lukou.time_3 = 1
            lukou.main_flag = 1
            group4.SetAttValue("TYPE", 3)  # 4变红
            group1.SetAttValue("TYPE", 2)  # 1变绿

    def default():
        return 0

    switch = {
        1: case1,
        2: case2,
        3: case3,
        4: case4
    }
    switch.get(lukou.main_flag, default)()


def Getbus4(i, Vissim, lukou1, detector1, detector2):
    import math
    # 四相位路口检测到公交车
    if detector2.AttValue("IMPULSE") == 1:
        # 检测器2检测到公交车，判断是否执行速度调节
        if lukou1.t_g_1 + lukou1.delta_t_g_max < (
                i + lukou1.l2 * 3.6 / lukou1.v_bus) % lukou1.T < lukou1.T - lukou1.delta_t_r_max:
            bus_id = int(detector2.AttValue("VEHICLEID"))
            bus = Vissim.Net.Vehicles.GetVehicleByNumber(bus_id)
            bus_speed = (lukou1.l2 - lukou1.l1) / (lukou1.t_g_1 - lukou1.time_1) * 3.6
            # QMessageBox.information(self, '提示', '速度调节', QMessageBox.Yes | QMessageBox.No)
            print('速度调节')
            bus.SetAttValue("SPEED", bus_speed)
            bus.SetAttValue("DESIREDSPEED", bus_speed)
            lukou1.delta_t = lukou1.delta_t_g_max
            lukou1.green_long_flag = True
            lukou1.speed_flag = True

        elif lukou1.T - lukou1.delta_t_r_max <= (i + lukou1.l2 * 3.6 / lukou1.v_bus) % lukou1.T < lukou1.T:
            lukou1.delta_t = lukou1.t_g_1 + lukou1.t_g_2 + lukou1.t_g_3 + lukou1.t_g_4 - int(
                math.ceil(lukou1.time_1 + lukou1.l2 * 3.6 / lukou1.v_bus)) + 1
            lukou1.red_short_flag = True

        if detector1.AttValue("IMPULSE") == 1:
            # 检测器1检测到公交车
            if not lukou1.speed_flag:
                # 且未执行加速
                if lukou1.time_1 + lukou1.l1 * 3.6 / lukou1.v_bus > lukou1.t_g_1:
                    # 绿灯延长
                    lukou1.delta_t = lukou1.time_1 + int(math.ceil(lukou1.l1 * 3.6 / lukou1.v_bus)) - lukou1.t_g_1
                    lukou1.green_long_flag = True
            else:
                # 执行过加速，将速度降低到正常速度
                bus_id = int(detector1.AttValue("VEHICLEID"))
                bus = Vissim.Net.Vehicles.GetVehicleByNumber(bus_id)
                bus.SetAttValue("SPEED", 35.0)
                bus.SetAttValue("DESIREDSPEED", 35.0)
                lukou1.speed_flag = False
